#include "server.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <regex> //包含了 C++ 标准库中的正则表达式支持
#include <sys/stat.h>
#include "http.hpp"

// void OnConnected(const PtrConnection &conn) {
//     DBG_LOG("NEW CONNECTION:%p", conn.get());
// }
// void OnClosed(const PtrConnection &conn) {
//     DBG_LOG("CLOSE CONNECTION:%p", conn.get());
// }
// void OnMessage(const PtrConnection &conn, Buffer *buf) {
//     DBG_LOG("%s", buf->ReadPosition());
//     buf->MoveReadOffset(buf->ReadAbleSize());
//     std::string str = "Hello World";
//     conn->Send(str.c_str(), str.size());
// }
// int main()
// {
//     TcpServer server(8500);
//     server.SetThreadCount(2);
//     server.EnableInactiveRelease(10);
//     server.SetClosedCallback(OnClosed);
//     server.SetConnectedCallback(OnConnected);
//     server.SetMessageCallback(OnMessage);
//     server.Start();
//     return 0;
// }

size_t Split(const std::string &src, const std::string &sep, std::vector<std::string> *arry)
{
    size_t offset = 0;
    while (offset < src.size())
    {
        size_t pos = src.find(sep, offset); // 在src字符串偏移量offset处，开始向后查找sep字符/字串，返回查找到的位置
        if (pos == std::string::npos)       ////没有找到特定的字符
        {                                   // 将剩余的部分当作一个字串，放入arry中
            // if (pos == src.size())
            //     break;
            arry->push_back(src.substr(offset));
            return arry->size();
        }
        if (pos == offset) // 起始位置紧接着分隔符
        {
            offset = pos + sep.size();
            continue; // 当前字串是一个空的，没有内容
        }
        arry->push_back(src.substr(offset, pos - offset));
        offset = pos += sep.size();
    }
    return arry->size();
}

bool ReadFile(const std::string &filename, std::string *buf)
{
    std::ifstream ifs(filename, std::ios::binary); // 文件输入流，以文件中的数据作为输入
    if (ifs.is_open() == false)
    {
        ERR_LOG("OPEN %s FILE FALLED!!", filename.c_str());
        return false;
    }
    size_t fsize = 0;
    ifs.seekg(0, ifs.end); // 跳转读写位置到末尾
    fsize = ifs.tellg();   // 获取当前读写位置相对于起始位置的偏移量，从末尾偏移刚好就是文件大小
    ifs.seekg(0, ifs.beg); // 跳转到起始位置
    buf->resize(fsize);    // 开辟文件大小的空间
    ifs.read(&(*buf)[0], fsize);
    if (ifs.good() == false)
    {
        ERR_LOG("READ %s FILE FAILED!", filename.c_str());
        ifs.close();
        return false;
    }
    ifs.close();
    return true;
}

bool WriteFile(const std::string &filename, const std::string &buf)
{
    std::ofstream ofs(filename, std::ios::binary | std::ios::trunc); // 文件输出流，将数据输出到文件
    if (ofs.is_open() == false)
    {
        ERR_LOG("OPEN %s FILE FAILED!!", filename.c_str());
        return false;
    }
    ofs.write(buf.c_str(), buf.size());
    if (ofs.good() == false)
    {
        ERR_LOG("WRITE %s FILE FAILED!", filename.c_str());
        ofs.close();
        return false;
    }
    ofs.close();
    return true;
}

std::string UrlEncode(const std::string url, bool convert_space_to_plus)
{
    std::string res;
    for (auto &c : url)
    {
        if (c == '.' || c == '-' || c == '_' || c == '~' || isalnum(c))
        {
            res += c;
            continue;
        }
        if (c == ' ' && convert_space_to_plus == true)
        {
            res += '+';
            continue;
        }
        // 剩下的字符都是需要编码成为 %HH 格式
        char tmp[4] = {0};
        snprintf(tmp, 4, "%%%02X", c);
        res += tmp;
    }
    return res;
}

static char HEXTOI(char c)
{
    if (c >= '0' && c <= '9')
    {
        return c - '0';
    }
    else if (c >= 'a' && c <= 'z')
    {
        return c - 'a' + 10;
    }
    else if (c >= 'A' && c <= 'Z')
    {
        return c - 'A' + 10;
    }
    return -1;
}

std::string UrlDecode(const std::string url, bool convert_plus_to_space)
{
    // 遇到了%，则将紧随其后的2个字符，转换为数字，第一个数字左移4位，然后加上第二个数字  + -> 2b  %2b->2 << 4 + 11
    std::string res;
    for (int i = 0; i < url.size(); i++)
    {
        if (url[i] == '+' && convert_plus_to_space == true)
        {
            res += ' ';
            continue;
        }
        if (url[i] == '%')
        {
            char v1 = HEXTOI(url[i + 1]);
            char v2 = HEXTOI(url[i + 2]);
            char v = v1 * 16 + v2; // 计算16进制转化后的字符串
            res += v;
            i += 2;
            continue;
        }
        res += url[i];
    }
    return res;
}

bool PraseHttpLine(const std::string &line, std::smatch &matches)
{
    std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
    // GET|HEAD|POST|PUT|DELETE   表示匹配并提取其中任意一个字符串
    //[^?]*     [^?]匹配非问号字符， 后边的*表示0次或多次
    //\\?(.*)   \\?  表示原始的？字符 (.*)表示提取?之后的任意字符0次或多次，知道遇到空格
    // HTTP/1\\.[01]  表示匹配以HTTP/1.开始，后边有个0或1的字符串
    //(?:\n|\r\n)?   （?: ...） 表示匹配某个格式字符串，但是不提取， 最后的？表示的是匹配前边的表达式0次或1次
    bool ret = std::regex_match(line, matches, e);
    std::string method = matches[1];
    std::transform(method.begin(), method.end(), method.begin(), ::toupper);
    std::cout << method << std::endl;
    for (int i = 0; i < matches.size(); i++)
    {
        std::cout << i << " : ";
        std::cout << matches[i] << std::endl;
    }
    return ret;
}

int main()
{
    // std::string src = "ab,ddadaaaaaaaaaaa,,,dawdawd";
    // std::string sep = ",";
    // std::vector<std::string> vs;
    // Split(src, sep, &vs);
    // for (auto e : vs)
    // {
    //     std::cout << e << std::endl;
    // }
    // std::string rstring;
    // ReadFile("./client.cpp", &rstring);
    // WriteFile("./test.txt", rstring);

    // std::string url = "/text.txt?username=rab&password=167493";
    // std::string Encodeurl = UrlEncode(url, false);
    // std::cout << Encodeurl << std::endl;
    // std::cout << UrlDecode(Encodeurl, false) << std::endl;

    // std::string str = "get /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n";
    std::smatch matches;
    std::string str1 = "GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\n";
    PraseHttpLine(str1, matches);
    std::string str2 = "get /bitejiuyeke/login HTTP/1.1\n";
    PraseHttpLine(str2, matches);
    return 0;
}